/**
 *
 * @author ihabali
 * @version 1.1
 * @className ExamController
 * @date 1st April 2014
 * @Assignment 3 ETP
 * @see ExamModel
 * 
 * This class will control and guide the user through the exam stage.
 * The class has an EJP property (an instance of ExamModel class) to handle all the
 * queries to the database in the background . 
 * This class is mainly handling events like redirecting to other pages 
 * ,handling errors , notify the business tier when to fetch information from database 
 * this class is not involved in the user login stage .
 *
 * 
 */

package controller;

import Entities.Questions;
import Entities.Usertable;
import com.sun.faces.component.visit.FullVisitContext;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import model.ExamModel;
import org.primefaces.component.commandbutton.CommandButton;



@ManagedBean(name="listControl")
@SessionScoped
public class ExamController implements Serializable {
    private String avg;
    private  List<Questions> questions;
    private  final long SerialVersionUID =  1L;
    private  Questions currentQuestion;
    private  int    questionNumber = 0 ;
    private int     progressMax;
    private int     progress;
    private  int    correctAnswer = 0 ; 
    private  float  average = 0f;
    private  String grade="";
    private boolean showPDFViewer = false;
    private boolean showAboutInfo =false;
    private boolean questionsPopulated = false;
    
    @EJB
    private ExamModel examModel;
    
    public ExamController(){
        examModel =  new ExamModel();
    }

    public ExamModel getExamModel() {
        return examModel;
    }

    public void setExamModel(ExamModel examModel) {
        this.examModel = examModel;
    }
    
    public String examSelectionListener(){
       System.out.println("exam set to : " +  examModel.getSelectedExam());
       return "/ExamInfoPage?faces-redirect=true";
    }

    public Questions getCurrentQuestion() {
        return currentQuestion;
    }
    
   static int  index;
   public void advanceToNext(){
     if (index < questions.size()-1 && index>=0) {
           ++index;
           currentQuestion = questions.get(index);
      }else{
         return;
     }
      handleButtons();
   }
   
   
   public void returnToPrevious(){
       if (index <= questions.size()-1 && index > 0) {
           --index;
           currentQuestion = questions.get(index);
            
       }else{
           return;
       }
      
      handleButtons();
   }

    public int getProgressMax() {
        progressMax = questions.size();
        return progressMax;
    }

    public int getProgress() {
        progress = 0;
        
        for(Questions q :  questions){
            if(q.getSavedanswer() != null){
                ++progress;
            }
        }
        return progress;
    }
   
   
   public void handleButtons(){
       CommandButton buttonG =  (CommandButton) findComponent("GradeButton");
       CommandButton buttonN =  (CommandButton) findComponent("nextQ");
       CommandButton buttonP =  (CommandButton) findComponent("previousQ");
       if(index==0){
           buttonG.setDisabled(true);
           buttonN.setDisabled(false);
           buttonP.setDisabled(true);
           
       }else if(index == questions.size()-1){
           buttonG.setDisabled(false);
           buttonN.setDisabled(true);
           buttonP.setDisabled(false);
           
       }else{
           
           buttonG.setDisabled(true);
           buttonN.setDisabled(false);
           buttonP.setDisabled(false);
           
       }
   }

    public void populateGrades()  {
        
        for (Questions q : questions) {
            if (q.getSavedanswer() != null) {
                if (q.getAnswer().trim().equals(q.getSavedanswer().trim())) {
                    ++correctAnswer;
                }
            }
        }
        
        average = (correctAnswer+0f) / (questions.size()+(0f)) * 100f;
        avg = String.format("%.1f",average);
        
        
        if (average >= 90 ){
            grade="A+";
        }else if (average <= 89 && average >= 85){
            grade="A";
        }else if (average <= 84 && average >= 80){
             grade="A-";
        }else if (average <= 79 && average >= 77){
             grade="B+";
        }else if (average <= 76 && average >= 73){
             grade="B";
        }else if (average <= 72 && average >= 70){
             grade="B-";
        }else if (average <= 69 && average >= 67){
             grade="C+";
        }else if (average <= 66 && average >= 63){
             grade="C";
        }else if (average <= 62 && average >= 60){
             grade="C-";
        }else if (average <= 59 && average >= 57){
             grade="D+";
        }else if (average <= 56 && average >= 53){
             grade="D";
        }else if (average <= 52 && average >= 50){
             grade="D-";
        }else if (average <= 49 && average >= 0){
             grade="F";
        }
       
    }
    
    public void downloadResults() throws FileNotFoundException, UnsupportedEncodingException {
        Usertable user = (Usertable) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("User");
        if (user != null) {
            System.out.println("Current User is" + user.getUsername() + "password is" + user.getUserpassword());
            PrintWriter writer = new PrintWriter(examModel.getSelectedEx().getTitle() + "-"
                    + user.getUsername() + ".csv", "UTF-8");
            writer.print(examModel.getSelectedEx().getTitle() + "," + user.getUsername()+ ",");

            for (Questions q : questions) {
                if (q.getSavedanswer() != null) {
                    if (q.getAnswer().trim().equals(q.getSavedanswer().trim())) {
                        writer.print("1,");
                    } else {
                        writer.print("0,");
                    }
                } else {
                    writer.print("0,");
                }
            }
            writer.print(correctAnswer+",");
            writer.println(this.avg +"," + this.grade);
            writer.close();
        }
        
    }
    public void handleTimer() throws IOException{
       if(this.examModel.getSwm().isIsRunning()){
          boolean willExpire = this.examModel.getSwm().handleTimer();
          if( willExpire){
              FacesContext context = FacesContext.getCurrentInstance();
              context.addMessage(null, new FacesMessage("Exam Time Will Expire in "+examModel.getSwm().getSeconds()+
                      " Seconds"));
          }
       }else{
         goToGradePage();
       }
   }
   
   public void goToGradePage() throws IOException{
        index=0;
        this.populateGrades();
        ExternalContext externContext = FacesContext.getCurrentInstance().getExternalContext();
        externContext.redirect(externContext.getRequestContextPath() + "/faces/GradingPage.xhtml" );
   }
    public String examBeginListener(){
        examModel.createSwm();
        examModel.setTheQuestions();
        this.questions = this.examModel.getSelectedEx().getQuestionsList();
        this.questionsPopulated = true;
        Collections.shuffle(questions);
        currentQuestion = questions.get(questionNumber);
        return "/ExamPage?faces-redirect=true";
    }

    public boolean isQuestionsPopulated() {
        return questionsPopulated;
    }
    
    public List<Questions> getQuestions() {
        return questions;
    }

    public int getCorrectAnswer() {
        return correctAnswer;
    }

    public String getGrade() {
        return grade;
    }

    public String getAvg() {
        return avg;
    }

   public String logOut(){
      index =0;
      this.examModel.cleanUp();
      FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("User");
      FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
      return "index?faces-redirect=true";
   }

    
    public void showPDF(){
        this.showPDFViewer = true;
    }
    
    public void showAbout(){
        System.out.println("Will set about page to true ");
        this.showAboutInfo = true;
    }

    public boolean isShowPDFViewer() {
        return showPDFViewer;
    }

    public boolean isShowAboutInfo() {
        return showAboutInfo;
    }
    
    
    
    public void dialogClosed(){
        showAboutInfo = false;
        showPDFViewer =false;
    }
    
    public UIComponent findComponent(final String id){
    FacesContext context = FacesContext.getCurrentInstance(); 
    UIViewRoot root = context.getViewRoot();
    final UIComponent[] found = new UIComponent[1];
    root.visitTree(new FullVisitContext(context), new VisitCallback() {     
        @Override
        public VisitResult visit(VisitContext context, UIComponent component) {
            if(component.getId().equals(id)){
                found[0] = component;
                return VisitResult.COMPLETE;
            }
            return VisitResult.ACCEPT;              
        }
    });
    return found[0];

}
}
